﻿#region Using Statements
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

#endregion

#region COPYRIGHT

/*
    Copyright (c) 2008, 2009, 2010 
        Roland Rosenkranz (Glatzemann@email.de)
*/

#endregion

#region LICENSE

/*
    This file is part of starLiGHT.Collision.

    starLiGHT.Collision is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    starLiGHT.Collision is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with starLiGHT.Collision.  If not, see <http://www.gnu.org/licenses/>.

    
    ADDITIONAL (commercial) LICENSES for starLiGHT.Collision are available on request.
*/

#endregion

#region Box2D Copyright
/*
* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
*
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#endregion

#region Version Stuff
// **************[ starLiGHT.Engine SVN ]**********************
// * $Rev:: 1486                  $:  Revision of last commit *
// * $Author:: glatzemann         $:  Author of last commit   *
// * $Date:: 2010-10-08 15:55:47 #$:  Date of last commit     *
// ************************************************************

// **************[ Box2D-Repository Info ]*********************
// Header-File: http://code.google.com/p/box2d/source/browse/trunk/Box2D/Box2D/Dynamics/b2WorldCallbacks.h
// Revision   : r71
// Change-Date: 2010-03-31
//
// Source-File: http://code.google.com/p/box2d/source/browse/trunk/Box2D/Box2D/Dynamics/b2WorldCallbacks.cpp
// Revision   : r109
// Change-Date: 2010-05-31
//
// Status     : Finished!
#endregion

namespace starLiGHT.Physic.TwoD
{
    public delegate float RayCastCallback(Fixture fixture, Vector2 point, Vector2 normal, float fraction);

    /// <summary>Joints and fixtures are destroyed when their associated
    /// body is destroyed. Implement this listener so that you
    /// may nullify references to these joints and shapes.</summary>
    public class DestructionListener
    {
        /// <summary>Called when any joint is about to be destroyed due
	    /// to the destruction of one of its attached bodies.</summary>
	    public virtual void SayGoodbye(Joint joint) {}

        /// <summary>Called when any fixture is about to be destroyed due
	    /// to the destruction of its parent body.</summary>
	    public virtual void SayGoodbye(Fixture fixture) {}
    };

    /// <summary>Implement this class to provide collision filtering. In other words, you can implement
    /// this class if you want finer control over contact creation.</summary>
    public class ContactFilter
    {
        /// <summary>Return true if contact calculations should be performed between these two shapes.</summary>
	    /// <remarks>for performance reasons this is only called when the AABBs begin to overlap.</remarks>
        public virtual bool ShouldCollide(Fixture fixtureA, Fixture fixtureB)
        {
	        Filter filterA;
            fixtureA.GetFilterData(out filterA);
	        Filter filterB;
            fixtureB.GetFilterData(out filterB);

	        if (filterA.groupIndex == filterB.groupIndex && filterA.groupIndex != 0)
	        {
		        return filterA.groupIndex > 0;
	        }

	        bool collide = (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0;
	        return collide;
        }
    };

    /// <summary>Contact impulses for reporting. Impulses are used instead of forces because
    /// sub-step forces may approach infinity for rigid body collisions. These
    /// match up one-to-one with the contact points in Manifold.</summary>
    public class ContactImpulse
    {
	    public float[] normalImpulses = new float[PhysicSettings.MaxManifoldPoints];
        public float[] tangentImpulses = new float[PhysicSettings.MaxManifoldPoints];
    };

    /// <summary>Implement this class to get contact information. You can use these results for
    /// things like sounds and game logic. You can also get contact results by
    /// traversing the contact lists after the time step. However, you might miss
    /// some contacts because continuous physics leads to sub-stepping.
    /// Additionally you may receive multiple callbacks for the same contact in a
    /// single time step.<br/><br/>
    /// You should strive to make your callbacks efficient because there may be
    /// many callbacks per time step.</summary>
    /// <remarks>You cannot create/destroy Box2D entities inside these callbacks.</remarks>
    public class ContactListener
    {
        /// <summary>Called when two fixtures begin to touch.</summary>
	    public virtual void BeginContact(Contact contact) { }

        /// <summary>Called when two fixtures cease to touch.</summary>
	    public virtual void EndContact(Contact contact) { }

        /// <summary>This is called after a contact is updated. This allows you to inspect a
	    /// contact before it goes to the solver. If you are careful, you can modify the
	    /// contact manifold (e.g. disable contact).<br/>
	    /// A copy of the old manifold is provided so that you can detect changes.</summary>
        /// <remarks>this is called only for awake bodies.<br/>
	    /// this is called even when the number of contact points is zero.<br/>
        /// this is not called for sensors.<br/>
        /// if you set the number of contact points to zero, you will not
	    /// get an EndContact callback. However, you may get a BeginContact callback
        /// the next step.<br/></remarks>
	    public virtual void PreSolve(Contact contact, Manifold oldManifold) { }

        /// <summary>This lets you inspect a contact after the solver is finished. This is useful
	    /// for inspecting impulses.
	    /// Note: the contact manifold does not include time of impact impulses, which can be
	    /// arbitrarily large if the sub-step is small. Hence the impulse is provided explicitly
	    /// in a separate data structure.
	    /// Note: this is only called for contacts that are touching, solid, and awake.</summary>
	    public virtual void PostSolve(Contact contact, ContactImpulse impulse) { }
    };

    public abstract class QueryCallback
    {
        public abstract bool ReportFixture(Fixture fixture);
    }

    /// <summary>         
    /// Implement and register this class with a World to provide debug drawing of physics         
    /// entities in your game.         
    /// </summary>         
    public abstract class DebugDraw
    {
        public abstract void updateCamera(ICamera2D camera, bool flipY);
        public abstract void DrawString(SpriteBatch spriteBatch, SpriteFont font, int x, int y, string text);
        public abstract void DrawPoint(Vector2 p, float size, Color color);

        public virtual void BeginFrame()
        {

        }

        public virtual void EndFrame()
        {

        }

        [Flags]
        public enum DrawFlags
        {
            Shape = 0x0001, // draw shapes                         
            Joint = 0x0002, // draw joint connections                         
            Aabb = 0x0004, // draw axis aligned bounding boxes                         
            Pair = 0x0008, // draw broad-phase pairs                         
            CenterOfMass = 0x0010, // draw center of mass frame                         
        };

        protected DrawFlags _drawFlags;

        public DebugDraw()
        {
            _drawFlags = DebugDraw.DrawFlags.Shape;
        }

        public DrawFlags Flags
        {
            get { return _drawFlags; }
            set { _drawFlags = value; }
        }

        /// <summary>                 
        /// Append flags to the current flags.                 
        /// </summary>                 
        public void AppendFlags(DrawFlags flags)
        {
            _drawFlags |= flags;
        }

        /// <summary>                 
        /// Clear flags from the current flags.                 
        /// </summary>                 
        public void ClearFlags(DrawFlags flags)
        {
            _drawFlags &= ~flags;
        }

        /// <summary>                 
        /// Draw a closed polygon provided in CCW order.                 
        /// </summary>                 
        public abstract void DrawPolygon(Vector2[] vertices, int vertexCount, Color color);

        /// <summary>                 
        /// Draw a solid closed polygon provided in CCW order.                 
        /// </summary>                 
        public abstract void DrawSolidPolygon(Vector2[] vertices, int vertexCount, Color color);

        /// <summary>                 
        /// Draw a circle.                 
        /// </summary>                 
        public abstract void DrawCircle(Vector2 center, float radius, Color color);

        /// <summary>                 
        /// Draw a solid circle.                 
        /// </summary>                 
        public abstract void DrawSolidCircle(Vector2 center, float radius, Vector2 axis, Color color);

        /// <summary>                 
        /// Draw a line segment.                 
        /// </summary>                 
        public abstract void DrawSegment(Vector2 p1, Vector2 p2, Color color);

        /// <summary>                 
        /// Draw a transform. Choose your own length scale.                 
        /// </summary>                 
        /// <param name="xf">A transform.</param>                 
        public abstract void DrawTransform(Transform xf);

        public abstract void DrawAABB(ref AABB aabb, Color color);
    } 

}
